/////////////////////////////////////////////////////////////////////////////
// This file is part of the "Java-DAP" project, a Java implementation
// of the OPeNDAP Data Access Protocol.
//
// Copyright (c) 2007 OPeNDAP, Inc.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
/////////////////////////////////////////////////////////////////////////////
using System;
using NDODS.DAP.BaseTypes;
using NDODS.DAP.Exceptions;
using NDODS.DAP.Server;
using NDODS.DAP.Utils;
using NDODS.DAP.XMLParser;
using NDODS.Util;

namespace NDODS.DAP
{
	
	/// <summary> The Alias type is a special attribute. It is simply a reference
	/// (like a "soft link" in a UNIX file system) to another attribute.
	/// <p/>
	/// The rules for the definiton and interpretation an Alias are as follows:
	/// <p/>
	/// In the persistent representation of the DDS (XML, or old DAS & DDS syntax)
	/// Alias definitions will contain 2 fields: name, attribute. Example from a DDS:
	/// <pre>
	/// Alias CalDate  .profiler.cast.conductivity.calibration.date
	/// </pre>
	/// Or a DDX:
	/// <pre>
	/// &lt;Alias name=&quot;CalDate&quot; attribute=&quot;.profiler.cast.conductivity.calibration.date&quot;/&gt;
	/// </pre>
	/// <p/>
	/// The rules for the interpretation of these fields are as follows:
	/// <ul>
	/// <li> Then Alias defintion begins with the word <code>Alias</code></li>
	/// <p/>
	/// <li> The name field is consumed in it's entirety (unparsed) and used
	/// as the name of the Alias.
	/// <p/>
	/// <li> There a number of rules specific to the representation and interpretation
	/// of the  attribute field in the Alias declaration.</li>
	/// <ul>
	/// <li> The &quot; (double quote) and the \ (backslash aka escape)
	/// characters MUST be escaped (using \ character) in the value of the attribute field.</li>
	/// <p/>
	/// <li> Each variable and attribute name in the attribute field must be enclosed
	/// in double quotes if their values contain the dot (.) character. For
	/// example: .sometimes."names.contain".dots would be three names <i>sometimes</i>,
	/// <i>names.contain</i>, and <i>dots</i>.</li>
	/// <p/>
	/// <li> Fully qualified attribute names always begin with
	/// the dot (.) character.</li>
	/// <p/>
	/// <li> All attribute names always MUST be fully qualified (begin with a dot).
	/// The leading dot represents a fully
	/// qualifed path attribute reference, starting at top level of DDX, or the DAS.</li>
	/// <p/>
	/// <p/>
	/// <li> If the attribute field contains only the dot (.) character, then it is
	/// referencing the collection of attributes associated with the highest level
	/// of the Dataset (global attributes) This collection always exists, but may be empty. </li>
	/// <p/>
	/// <li> The attribute field MUST NOT be empty.</li>
	/// <li> The attribute field MUST NOT point to another Alias.</li>
	/// </ul>
	/// <p/>
	/// <li> After the parser has completely parsed the DDX (or DAS) it will attempt to
	/// reslove each alias to a specific attribute. If an alias cannot be resolved to
	/// some attribute, and exception will be thrown by the parser.</li>
	/// <p/>
	/// </ul>
	/// <p/>
	/// <b>Warning:</b> <code>DAS</code> and <code>DDS</code> objects built using methods other than
	/// <code>DDS.parse()</code>, <code>DDS.parseXML</code>,
	/// <code>DDS.getDAS()</code>, or <code>DAS.parse()</code>
	/// must call <code>DDS.resolveAliases()</code> or <code>DAS.resolveAliases()</code> prior to
	/// allowing client software access to
	/// these objects. Since an <code>Alias</code> essentially represents a "pointer" to some (other)
	/// <code>Attribute</code>, that
	/// <code>Attribute</code> object must be found. Once this has been done (by calling the correct
	/// <code>resolveAliases()</code> method)
	/// the <code>Aliases</code> will act transparently as references to their target <code>Attributes</code>.
	/// 
	/// </summary>
	/// <author>  ndp
	/// </author>
	/// <version>  $Revision: 15901 $
	/// </version>
	/// <seealso cref="AttributeTable">
	/// </seealso>
	/// <seealso cref="DDS">
	/// </seealso>
	/// <seealso cref="DDS.parse">
	/// </seealso>
	/// <seealso cref="DDS.parseXML">
	/// </seealso>
	/// <seealso cref="DDS.getDAS">
	/// </seealso>
	/// <seealso cref="DAS">
	/// </seealso>
	/// <seealso cref="DAS.resolveAliases">
	/// </seealso>
	[Serializable]
	public class Alias:Attribute, System.ICloneable
	{
		virtual public BaseType MyVariable
		{
			set
			{
				targetVariable = value;
			}
			
		}
		/// <summary> Returns the attribute type constant.
		/// 
		/// </summary>
		/// <returns> the attribute type constant.
		/// </returns>
		override public int Type
		{
			get
			{
				
				return (getMyAttribute().Type);
			}
			
		}
		/// <summary> Returns the name of the attribute aliased to.
		/// 
		/// </summary>
		/// <returns> the name of the attribute aliased to.
		/// </returns>
		virtual public System.String AliasedTo
		{
			get
			{
				return "";
			}
			
		}
		/// <summary> Returns the name of the attribute aliased to.
		/// 
		/// </summary>
		/// <returns> the name of the attribute aliased to.
		/// </returns>
		virtual public System.String AliasedToAttributeFieldAsClearString
		{
			get
			{
				return aliasedToAttributeNamed;
			}
			
		}
		/// <summary> Returns the name of the attribute aliased to.
		/// 
		/// </summary>
		/// <returns> the name of the attribute aliased to.
		/// </returns>
		virtual public System.String AliasedToAttributeField
		{
			get
			{
				return EscapeStrings.id2www(aliasedToAttributeNamed);
			}
			
		}
		/// <summary> Returns the values of this attribute as an <code>Enumeration</code>
		/// of <code>String</code>.
		/// 
		/// </summary>
		/// <returns> an <code>Enumeration</code> of <code>String</code>.
		/// </returns>
		override public System.Collections.IEnumerator Values
		{
			get
			{
				return (getMyAttribute().Values);
			}
			
		}
		
		
		/// <summary> If <code>is_alias</code> is true, the name of the <code>Attribute</code>
		/// we are aliased to.
		/// </summary>
		private System.String aliasedToAttributeNamed;
		
		
		/// <summary> The Attribute to which this Alias points.</summary>
		private Attribute targetAttribute;
		
		/// <summary> The BaseType variable that contains the Attribute
		/// to which this Alias points.
		/// </summary>
		private BaseType targetVariable;
		
		/// <summary> Construct an Alias. This constructor is used by the DDSXMLParser to
		/// and the DAS parser build Aliases for the DDX.
		/// 
		/// </summary>
		/// <param name="aName">        a <code>String</code> containing the name of the alias.
		/// </param>
		/// <param name="attributeName">the <code>String</code> containing the normalized name
		/// of the variable and attribute that this Alias references.
		/// </param>
		public Alias(System.String aName, System.String attributeName):base(aName, ALIAS)
		{
			aliasedToAttributeNamed = attributeName;
			targetAttribute = null;
			targetVariable = null;
		}
		
		/// <summary> Returns a clone of this <code>Attribute</code>.  A deep copy is performed
		/// on all attribute values.
		/// 
		/// </summary>
		/// <returns> a clone of this <code>Attribute</code>.
		/// </returns>
		public override System.Object Clone()
		{
			
			
			Alias a = (Alias) base.Clone();
			
			a.aliasedToAttributeNamed = this.aliasedToAttributeNamed;
			a.targetAttribute = this.targetAttribute;
			a.targetVariable = this.targetVariable;
			
			return (a);
		}
		
		public virtual void  setMyAttribute(Attribute a)
		{
			targetAttribute = a;
		}
		
		private Attribute getMyAttribute()
		{
			
			return (targetAttribute);
		}
		
		//    private BaseType getMyVariable() {
		//        return (targetVariable);
		//    }
		
		
		/// <summary> Returns true if the attribute is a container.
		/// 
		/// </summary>
		/// <returns> true if the attribute is a container.
		/// </returns>
		public override bool isContainer()
		{
			return (getMyAttribute().Type == CONTAINER);
		}
		
		/// <summary> Returns true if the attribute is an alias.
		/// 
		/// </summary>
		/// <returns> true if the attribute is an alias.
		/// </returns>
		public override bool isAlias()
		{
			return true;
		}
		
		/// <summary> Returns the <code>AttributeTable</code> container.
		/// 
		/// </summary>
		/// <returns> the <code>AttributeTable</code> container.
		/// </returns>
		public override AttributeTable getContainer()
		{
			return (getMyAttribute().getContainer());
		}
		
		/// <summary> Returns the attribute value at <code>index</code>.
		/// 
		/// </summary>
		/// <param name="index">the index of the attribute value to return.
		/// </param>
		/// <returns> the attribute <code>String</code> at <code>index</code>.
		/// </returns>
		public override System.String getValueAt(int index)
		{
			return (getMyAttribute().getValueAt(index));
		}
		
		/// <summary> Append a value to this attribute. Always checks the validity of the
		/// attribute's value.
		/// 
		/// </summary>
		/// <param name="value">the attribute <code>String</code> to add.
		/// </param>
		/// <throws>  AttributeBadValueException thrown if the value is not a legal </throws>
		/// <summary>                                    member of type
		/// </summary>
		public override void  appendValue(System.String value_Renamed)
		{
			
			throw new AttributeBadValueException("It is illegal to add values to an Alias. " + "Values can only be added to an Attribute");
		}
		
		/// <summary> Append a value to this attribute.
		/// 
		/// </summary>
		/// <param name="value">the attribute <code>String</code> to add.
		/// </param>
		/// <param name="check">if true, check the validity of he attribute's value, if
		/// false don't.
		/// </param>
		/// <throws>  AttributeBadValueException thrown if the value is not a legal </throws>
		/// <summary>                                    member of type
		/// </summary>
		public override void  appendValue(System.String value_Renamed, bool check)
		{
			
			throw new AttributeBadValueException("It is illegal to add values to an Alias. " + "Values can only be added to an Attribute");
		}
		
		/// <summary> Remove the <code>i</code>'th <code>String</code> from this attribute.
		/// 
		/// </summary>
		/// <param name="index">the index of the value to remove.
		/// </param>
		public override void  deleteValueAt(int index)
		{
			throw new AttributeBadValueException("It is illegal to remove values from an Alias. " + "Values can only be removed from an Attribute");
		}
		
		
		public override void  print(System.IO.StreamWriter os, System.String pad)
		{
			
			if (Debug.isSet("Alias"))
				System.Console.Out.WriteLine("  Attribute \"" + ClearName + "\" is an Alias.");
			
			//UPGRADE_TODO: Method 'java.io.StreamWriter.println' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioStreamWriterprintln_javalangString'"
			os.WriteLine(pad + "Alias " + Name + " " + AliasedToAttributeField + ";");
		}
		
		
		public override void  printXML(System.IO.StreamWriter pw, System.String pad, bool constrained)
		{
			
			
			if (Debug.isSet("Alias"))
			{
				//UPGRADE_TODO: Method 'java.io.StreamWriter.println' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioStreamWriterprintln_javalangString'"
				pw.WriteLine("    Printing Alias \"" + ClearName + "\"");
			}
			
			/*
			if (Debug.isSet("Alias")) pw.println("       constrained:    "+constrained);
			if (Debug.isSet("Alias")) pw.println("       targetVariable: '"+targetVariable.getName()+
			"' (Projected: "+((ServerMethods) targetVariable).isProject()+")");*/
			
			if (constrained && targetVariable != null && targetVariable is IServerMethods)
			{
				
				
				IServerMethods sm = (IServerMethods) targetVariable;
				if (!sm.isProject())
					return ;
			}
			
			
			//UPGRADE_TODO: Method 'java.io.StreamWriter.println' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioStreamWriterprintln_javalangString'"
			pw.WriteLine(pad + "<Alias name=\"" + DDSXMLParser.normalizeToXML(ClearName) + "\" " + "Attribute=\"" + DDSXMLParser.normalizeToXML(AliasedToAttributeFieldAsClearString) + "\"/>");
			
			if (Debug.isSet("Alias"))
			{
				//UPGRADE_TODO: Method 'java.io.StreamWriter.println' was converted to 'System.IO.TextWriter.WriteLine' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioStreamWriterprintln_javalangString'"
				pw.WriteLine("Leaving Alias.Print()");
			}
			pw.Flush();
		}
	}
	
	// $Log: Alias.java,v $
	// Revision 1.2  2003/09/02 17:49:34  ndp
	// *** empty log message ***
	//
	// Revision 1.1  2003/08/12 23:51:24  ndp
	// Mass check in to begin Java-OPeNDAP development work
	//
	// Revision 1.5  2003/02/12 16:41:15  ndp
	// *** empty log message ***
	//
	// Revision 1.4  2002/12/03 22:44:15  ndp
	// *** empty log message ***
	//
	// Revision 1.3  2002/10/26 01:19:40  ndp
	// *** empty log message ***
	//
	// Revision 1.1  2002/10/08 23:03:23  ndp
	// *** empty log message ***
	//
	// Revision 1.6  2002/08/27 04:30:11  ndp
}